ReactNative 例子
Table of Contents
新建项目
npm info react-native # 查看版本信息 react-native init App --version 0.51.0 # 版本号可以通过上一步得到 cd App react-native run-android
Hello World
进入项目根目录, 将 App.js 下的代码替换如下:
import React, { Component } from 'react'; import { Text } from 'react-native'; export default class HelloWorldApp extends Component { render() { return ( <Text>Hello world!</Text> ); } }
执行 react-native run-android, 打开程序, 可以看到 Hello World.
展示电影程序
场景: 从电影数据库中取得最近正在上映的 25 部电影, 并在一个 FlatList 中展示出来.
展示模拟数据
将以下代码覆盖到 App.js 文件:
import React, { Component } from 'react'; import { AppRegistry, Image, StyleSheet, Text, View, } from 'react-native'; var MOCKED_MOVIES_DATA = [ {title: '标题', year: '2015', posters: {thumbnail: 'http://i.imgur.com/UePbdph.jpg'}}, ]; export default class HelloWorldApp extends Component { render() { var movie = MOCKED_MOVIES_DATA[0]; return ( <View style={styles.container}> <Text>{movie.title}</Text> <Text>{movie.year}</Text> <Image source={{uri: movie.posters.thumbnail}} style={styles.thumbnail} /> </View> ); } } // 添加样式 var styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, thumbnail: { width: 53, height: 81, }, });
修改样式
如果要将文字显示在图片的右边, 再放大标题, 需要修改样式.
我们增加一个 container, 实现在一个水平布局内嵌套一个垂直布局.
修改部分代码:
export default class HelloWorldApp extends Component { render() { var movie = MOCKED_MOVIES_DATA[0]; return ( <View style={styles.container}> <Image source={{uri: movie.posters.thumbnail}} style={styles.thumbnail} /> <View style={styles.rightContainer}> <Text>{movie.title}</Text> <Text>{movie.year}</Text> </View> </View> ); } } // 添加样式 var styles = StyleSheet.create({ container: { flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, thumbnail: { width: 53, height: 81, }, rightContainer: { flex: 1, }, title: { fontSize: 20, marginBottom: 8, textAlign: 'center', }, year: { textAlign: 'center', }, });
拉取真正的数据
将 REQUEST_URL 常量放到 import 下面:
var REQUEST_URL = 'https://raw.githubusercontent.com/facebook/react-native/0.51-stable/docs/MoviesExample.json';
初始化(放在 render() 之前):
constructor(props) { super(props); this.state = { movies: null, }; this.fetchData = this.fetchData.bind(this); }
组件加载完毕后, 就可以向服务器请求数据了. componentDidMount() 是 React 组件的一个生命周期方法, 会在组件刚加载完成的时候调用一次, 以后不再调用.
componentDidMount() { this.fetchData(); }
fetchData():
fetchData() { fetch(REQUEST_URL) .then((response) => response.json()) .then((responseData) => { this.setState({ movies: responseData.movies, }); }); }
修改 render():
render() { if (!this.state.movies) { return this.renderLoadingView(); } var movie = this.state.movies[0]; return this.renderMovie(movie); } renderLoadingView() { return ( <View style={styles.container}> <Text>正在加载电影数据...</Text> </View> ); } renderMovie(movie) { return ( <View style={styles.container}> <Image source={{uri: movie.posters.thumbnail}} style={styles.thumbnail} /> <View style={styles.rightContainer}> <Text style={styles.title}>{movie.title}</Text> <Text style={styles.year}>{movie.year}</Text> </View> </View> ); }
FlatList
FlatList 只显示当前屏幕上的元素, 对于那些已经渲染好了, 但移动到了屏幕之外的元素, 则会从原生视图结构中移除, 以提高性能.
先在文件最开头引入 FlatList:
import { ... FlatList, ... } from 'react-native';
修改 render():
render() { if (!this.state.loaded) { return this.renderLoadingView(); } return ( <FlatList data={this.state.data} renderItem={this.renderMovie} style={styles.list} /> ); }
修改 constructor():
constructor(props) { super(props); this.state = { data: [], loaded: false, }; // 在ES6中,如果在自定义的函数里使用了this关键字,则需要对其进行“绑定”操作,否则this的指向不对 // 像下面这行代码一样,在constructor中使用bind是其中一种做法(还有一些其他做法,如使用箭头函数等) this.fetchData = this.fetchData.bind(this); }
修改 fetchData():
fetchData() { fetch(REQUEST_URL) .then((response) => response.json()) .then((responseData) => { // 注意,这里使用了this关键字,为了保证this在调用时仍然指向当前组件,我们需要对其进行“绑定”操作 this.setState({ data: this.state.data.concat(responseData.movies), loaded: true, }); }); }
添加样式:
list: { paddingTop: 20, backgroundColor: '#F5FCFF', },
调试
使用 Chrome 来调试 React Native 程序
启动远程调试
摇晃手机, 点击 Debug JS Remotely.
同时会电脑会自动打开一个页面: http://localhost:8081/debugger-ui
打开 Chrome 开发者工具
按下 F12.
Sources 面板下, 可以看到 debuggerWorker.js. 将其层层打开, 可以看到我们的程序.
常见错误
Unable to load script from assets 'index.android.bundle'.
进入项目根目录:
mkdir -p android/app/src/main react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/ react-native run-android
我们可以把第二条命令写到 package.json 的 "script" 字段(与 "dependencies" 字段同级)中:
"android-linux": "react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res && react-native run-android"
然后通过 npm run android-linux 即可.
Could not connect to development server
adb reverse tcp:8081 tcp:8081 # 如果还不行 npm start
如果提示端口占用:
sudo lsof -i :8081 kill -9 xxx
Generated by Emacs 25.x(Org mode 8.x)
Copyright © 2014 - Pinvon - Powered by EGO